/* 
  An in-memory cache, improves the performance by making sure 
  that the most frequently used objects are in memory, and seeks to
  disk and the network are avoided.

  NOT TO BE CONFUSED BY THE BACKEND SERVICE THAT MANAGES THE NETWORK
  COMMUNICATION, AND MAINTAINS IT'S OWN DISK BASED CACHE OF OBJECTS
*/

#ifndef __CACHE_H__
#define __CACHE_H__

#include "object.h"

/* 
  The number of objects to be kept in the cache. This directly affects the
  memory requirements. CACHE_COUNT*MAX_DATA_OBJ memory is dedicated to 
  cache. Make sure that this product is sufficiently less than the amount 
  of RAM that you have in your machine. In case you do not care about such
  warnings, you should be punished >:)
*/
#define CACHE_COUNT 5


/* Individual cache entry. Let's call them centry */
typedef struct {
  object_id id;
  object obj;
  char obj_buf[MAX_DATA_OBJ];
  int is_dirty;
  int last_access;
  int last_access_us;
} centry;

void dump_cache ();
/* Initializes the cache by allocating the memory */
void init_cache ();

/* 
  Cleanup function. Writes the dirty pages, and frees the memory.
  To be called at shutdown.
*/ 
void destroy_cache ();

/*
  Flush function. Flushes ALL the dirty entries in the cache to the
  backend Disk based cache. The cached objects are still in the 
  memory, and are not simply purged. Therefore, it is safe to call
  this function every few minutes, seconds. hours, days, or whenever 
  you think suits you.
*/
void flush_all_cache ();


/*
  Reads an object corresponding to a particular object_id from the 
  cache. If there is a cache miss, evicts the least recently used
  object from the cache (writes the object back in case it is dirty)
  Also updates the last access time.

  In case a specific version of the object is asked for, the situation
  is a little complex, because we typically do not have the version
  information of the objects in the cache. [The cached objects are 
  there because somebody asked for the latest version of the objects,
  and we just fetched it by calling the get_object from the disk 
  based cache (which doesn't give version information anyways)]. Since
  asking for a specific version is not the common case, the way to
  resolve it is: if a version of the object exists in the cache, write
  it back to the disk. After that, simply fetch the requested object.
  
  All the conditions related to the object_id apply here as well.
*/

int get_object_c (object_id *id, object *obj, 
                      size_t max_length, char *buf);


/*
  If the corresponding object is already in the cache, writes to the
  in-memory version, and marks in-memory version dirty.

  The cache only contains the latest version of a particular object

  In case the object is not present in the cache, bring it into the 
  cache first, and follow the above steps. 

  All the conditions related to the object_id apply here as well.
*/

void put_object_c (object_id *id, object *obj);


/*
  Flushes a particular object from the cache.
  Useful for filesystem flush
*/
void flush_object (object_id *id);

#endif /* __CACHE_H__ */
